00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef _global_vector_hpp_
00022 #define _global_vector_hpp_
00023
00024 #include <iostream>
00025 #include <ga.h>
00026 #include "gridpack/utilities/exception.hpp"
00027 #include "gridpack/parallel/communicator.hpp"
00028
00029 namespace gridpack {
00030 namespace parallel {
00031
00032
00033
00034
00035 template <typename _data_type >
00036 class GlobalVector {
00037 private:
00038 gridpack::parallel::Communicator p_comm;
00039 public:
00040
00041
00042
00043
00044
00045
00046 GlobalVector(const gridpack::parallel::Communicator &comm)
00047 : p_comm(comm)
00048 {
00049 p_datasize = sizeof(_data_type);
00050 p_me = comm.rank();
00051 p_nprocs = comm.size();
00052 p_uploaded = false;
00053 }
00054
00055
00056
00057
00058 ~GlobalVector(void)
00059 {
00060 if (p_uploaded) {
00061 NGA_Deregister_type(p_GA_Type);
00062 GA_Destroy(p_GA);
00063 }
00064 }
00065
00066
00067
00068
00069
00070
00071 void addElements(const std::vector<int> &idx,
00072 const std::vector<_data_type> &vec)
00073 {
00074 int i, size;
00075 size = vec.size();
00076 for (i=0; i<size; i++) {
00077 p_index.push_back(idx[i]);
00078 p_data.push_back(vec[i]);
00079 }
00080 }
00081
00082
00083
00084
00085
00086 void upload()
00087 {
00088
00089
00090
00091 int max_idx = -1;
00092 int i;
00093 int one = 1;
00094 for (i=0; i<p_index.size(); i++) {
00095 if (p_index[i] < 0) {
00096 char buf[256];
00097 sprintf(buf,"Index %d less than zero in GlobalVector::upload on process %d\n",
00098 p_index[i],p_me);
00099 printf("%s",buf);
00100 throw gridpack::Exception(buf);
00101 }
00102 if (p_index[i] > max_idx) max_idx = p_index[i];
00103 }
00104 p_comm.max(&max_idx,1);
00105 p_numElems = max_idx+1;
00106
00107 if (p_numElems < 1) {
00108 char buf[256];
00109 sprintf(buf,"Vector has no data in GlobalVector::upload on process %d\n",
00110 p_me);
00111 printf("%s",buf);
00112 throw gridpack::Exception(buf);
00113 }
00114
00115
00116
00117 int g_idx = NGA_Create_handle();
00118 GA_Set_data(g_idx, one, &p_numElems, C_INT);
00119 int GAgrp = p_comm.getGroup();
00120 GA_Set_pgroup(g_idx, GAgrp);
00121 GA_Allocate(g_idx);
00122 int *iarr = new int[p_index.size()];
00123 int **iptr = new int*[p_index.size()];
00124 int *ival = new int[p_index.size()];
00125 GA_Zero(g_idx);
00126 for (i=0; i<p_index.size(); i++) {
00127 iarr[i] = p_index[i];
00128 iptr[i] = &iarr[i];
00129 ival[i] = one;
00130 }
00131 NGA_Scatter_acc(g_idx,ival,iptr,p_index.size(),&one);
00132 delete [] ival;
00133 int ilo, ihi, ld;
00134 int *lptr;
00135 NGA_Distribution(g_idx,p_me,&ilo,&ihi);
00136 NGA_Access(g_idx,&ilo,&ihi,&lptr,&ld);
00137 ld = ihi-ilo+1;
00138 for (i=0; i<ld; i++) {
00139 if (lptr[i] > 1) {
00140 char buf[256];
00141 sprintf(buf,"GlobalVector::upload Multiple elements for index %d on process %d\n",
00142 i+ilo,p_me);
00143 printf("%s",buf);
00144 throw gridpack::Exception(buf);
00145 }
00146 }
00147 NGA_Release(g_idx,&ilo,&ihi);
00148 GA_Destroy(g_idx);
00149
00150
00151 p_GA_Type = NGA_Register_type(p_datasize);
00152 p_GA = GA_Create_handle();
00153 GA_Set_data(p_GA, one, &p_numElems, p_GA_Type);
00154 GA_Set_pgroup(p_GA, GAgrp);
00155 GA_Allocate(p_GA);
00156
00157
00158 _data_type *dptr;
00159 NGA_Distribution(p_GA,p_me,&ilo,&ihi);
00160 NGA_Access(p_GA,&ilo,&ihi,&dptr,&ld);
00161 ld = ihi-ilo+1;
00162 memset(dptr,'\0',ld*p_datasize);
00163 NGA_Release(p_GA,&ilo,&ihi);
00164
00165
00166 _data_type *data = new _data_type[p_index.size()];
00167 for (i=0; i<p_index.size(); i++) {
00168 data[i] = p_data[i];
00169 }
00170 NGA_Scatter(p_GA,data,iptr,p_index.size());
00171 delete [] iarr;
00172 delete [] iptr;
00173 delete [] data;
00174 p_data.clear();
00175 p_index.clear();
00176 p_uploaded = true;
00177 GA_Pgroup_sync(GAgrp);
00178 }
00179
00180
00181
00182
00183
00184
00185
00186 void getData(const std::vector<int> &idx, std::vector<_data_type> &vec)
00187 {
00188 int i;
00189 for (i=0; i<idx.size(); i++) {
00190 if (idx[i] < 0 || idx[i] >= p_numElems) {
00191 char buf[256];
00192 sprintf(buf,"GlobalVector::getData Requested vector index %d out of range on process %d\n",
00193 idx[i],p_me);
00194 printf("%s",buf);
00195 throw gridpack::Exception(buf);
00196 }
00197 }
00198 int *iarr = new int[idx.size()];
00199 int **iptr = new int*[idx.size()];
00200 for (i=0; i<idx.size(); i++) {
00201 iarr[i] = idx[i];
00202 iptr[i] = &iarr[i];
00203 }
00204 _data_type *dbuf = new _data_type[idx.size()];
00205 NGA_Gather(p_GA,dbuf,iptr,idx.size());
00206
00207 vec.clear();
00208 for (int i=0; i<idx.size(); i++) {
00209 vec.push_back(dbuf[i]);
00210 }
00211 delete [] iarr;
00212 delete [] iptr;
00213 delete [] dbuf;
00214 };
00215
00216
00217
00218
00219
00220 void getAllData(std::vector<_data_type> &vec)
00221 {
00222 vec.clear();
00223 vec.resize(p_numElems);
00224 int lo, hi;
00225 int one = 1;
00226 lo = 0;
00227 hi = p_numElems-1;
00228 NGA_Get(p_GA,&lo,&hi,&vec[0],&one);
00229 }
00230
00231 private:
00232
00233 std::vector<_data_type> p_data;
00234 std::vector<int> p_index;
00235
00236
00237 int p_GA;
00238
00239
00240
00241 int p_datasize;
00242 int p_me;
00243 int p_nprocs;
00244 int p_numElems;
00245 int p_GA_Type;
00246
00247
00248 bool p_uploaded;
00249 };
00250 }
00251 }
00252
00253 #endif
00254